package com.ie.cloud.payment.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.http.HttpStatus;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.icbc.api.response.PaymentDetailQueryResponseV1;
import com.ie.cloud.payment.constants.BizStatus;
import com.ie.cloud.payment.dto.GeneralOrderDto;
import com.ie.cloud.payment.dto.PayDetailQueryDto;
import com.ie.cloud.payment.entity.MchApp;
import com.ie.cloud.payment.entity.PayOrder;
import com.ie.cloud.payment.entity.PayOrderFlowRecord;
import com.ie.cloud.payment.exception.BizException;
import com.ie.cloud.payment.mapper.MchAppMapper;
import com.ie.cloud.payment.mapper.PayOrderFlowRecordMapper;
import com.ie.cloud.payment.mapper.PayOrderMapper;
import com.ie.cloud.payment.request.MyPaymentDetailQueryRequestV1;
import com.ie.cloud.payment.utils.DateUtils;
import com.ie.cloud.payment.vo.MyPayDetailQueryResponseVo;
import com.ie.cloud.payment.vo.PayOrderVo;
import com.ie.cloud.payment.vo.base.Result;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * Created with FR
 *
 * @Author: DQ
 * @Date: 2025/07/22/12:12
 * @Description: 描述语句
 */
@Service
@Slf4j
public class PayOrderFlowRecordServiceImpl extends ServiceImpl<PayOrderFlowRecordMapper, PayOrderFlowRecord> {

    @Resource
    private ICBCServiceImpl icbcService;

    @Resource
    private MchAppMapper mchAppMapper;

    @Resource
    private PayOrderMapper payOrderMapper;

    @Resource
    SqlSessionFactory sqlSessionFactory;


    /**
     * 拉取流水记录
     */
    public void pullFlowRecord(String trxDate) {


        log.info("拉取流水记录,时间 {},交易日期 {}", LocalDateTime.now(), trxDate);


        List<MchApp> mchApps = mchAppMapper.selectList(MchApp.gw());


        ArrayList<PaymentDetailQueryResponseV1.PaymentDetaiQueryResponseV1Trade> totalTradeList = new ArrayList<>();


        for (MchApp mchApp : mchApps) {





            PayDetailQueryDto queryDto = new PayDetailQueryDto();
            queryDto.setAppId(mchApp.getAppId());
            queryDto.setCorpCis(mchApp.getMchNo());
            queryDto.setProjectId(mchApp.getProjectId());
            queryDto.setTrxDate(trxDate);
            queryDto.setTrxTimeStart("00:00:01");
            queryDto.setTrxTimeEnd("23:59:59");


            Result<MyPayDetailQueryResponseVo> firstPageDetailResponse = this.paymentDetailQuery(queryDto);

            if (firstPageDetailResponse.getCode() == HttpStatus.HTTP_OK && firstPageDetailResponse.getData().getTradeList() != null) {
                String curPage;
                String totalNum = firstPageDetailResponse.getData().getTotalNum();//总数
                int totalPage = Integer.parseInt(totalNum) / Integer.parseInt(queryDto.getFetchNum());//总页数

                for (int i = 1; i < totalPage; i++) {
                    //开始翻页
                    curPage = String.valueOf(i);
                    queryDto.setCurPage(curPage);
                    Result<MyPayDetailQueryResponseVo> nextPageDetailResponse = this.paymentDetailQuery(queryDto);//下一页的流水记录
                    if (nextPageDetailResponse.getCode() == HttpStatus.HTTP_OK) {
                        totalTradeList.addAll(nextPageDetailResponse.getData().getTradeList());
                    }
                }
                //将第一页的流水记录添加到总流水记录中
                totalTradeList.addAll(firstPageDetailResponse.getData().getTradeList());
            }
        }




        log.info("{},流水记录 {}",trxDate,totalTradeList.size());

        SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);//开启会话

        try {
            if (!totalTradeList.isEmpty()) {


                PayOrderFlowRecordMapper mapper = sqlSession.getMapper(PayOrderFlowRecordMapper.class);

                List<String> payOrderIdSet = totalTradeList.stream()
                        .map(PaymentDetailQueryResponseV1.PaymentDetaiQueryResponseV1Trade::getBusiCode)
                        .collect(Collectors.toList());

                Set<String> transRefGuidSet = totalTradeList.stream()
                        .map(PaymentDetailQueryResponseV1.PaymentDetaiQueryResponseV1Trade::getTransRefGuid)
                        .collect(Collectors.toSet());

                Set<String> payRefguidSet = totalTradeList.stream()
                        .map(PaymentDetailQueryResponseV1.PaymentDetaiQueryResponseV1Trade::getPayRefguid)
                        .collect(Collectors.toSet());

                List<PayOrderFlowRecord> existFlowRecordList = mapper.selectList(new LambdaQueryWrapper<PayOrderFlowRecord>()
                        .in(PayOrderFlowRecord::getPayOrderId, payOrderIdSet)
                        .in(PayOrderFlowRecord::getPayRefguid, payRefguidSet)
                        .in(PayOrderFlowRecord::getTransRefGuid, transRefGuidSet));

                Map<String, PayOrderFlowRecord> existFlowRecordMap = new HashMap<>();

                if (CollectionUtil.isNotEmpty(existFlowRecordList)) {
                    existFlowRecordMap = existFlowRecordList.stream().collect(Collectors.toMap(e ->
                                    String.format("%s%s%s",
                                            e.getPayOrderId(), e.getTransRefGuid(), e.getPayRefguid()),
                            k1 -> k1, (o1, o2) -> o1));
                }

                for (PaymentDetailQueryResponseV1.PaymentDetaiQueryResponseV1Trade trade : totalTradeList) {
                    if (existFlowRecordMap.get(String.format("%s%s%s",trade.getBusiCode(),trade.getTransRefGuid(),trade.getPayRefguid())) == null) {
                        PayOrderFlowRecord record = new PayOrderFlowRecord();
                        BeanUtil.copyProperties(trade, record);
                        record.setTrxDate(DateUtils.strToLocalDateTime(String.format("%s %s",trade.getTrxDate(),trade.getTrxTime())));
                        record.setPayOrderId(trade.getBusiCode());
                        mapper.insert(record);
                    }
                }

                sqlSession.commit();
            }
        }catch (BizException e) {
            log.error("流水记录更新异常 {}",e.getMessage());
            sqlSession.rollback();
        }finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
        }


    }


    @SuppressWarnings("Duplicated")
    public void pullFlowRecord(String trxDate, String busiCode,String appId) {
        log.info("拉取流水记录,时间 {},交易日期 {},busiCode {},appId {}", LocalDateTime.now(), trxDate,busiCode,appId);


        MchApp mchApp = mchAppMapper.selectOne(MchApp.gw().eq(MchApp::getAppId, appId));

        if (mchApp == null) {
            throw new BizException(BizStatus.MERCHANT_DOES_NOT_EXIST);
        }

        ArrayList<PaymentDetailQueryResponseV1.PaymentDetaiQueryResponseV1Trade> totalTradeList = new ArrayList<>();

        PayDetailQueryDto queryDto = new PayDetailQueryDto();
        queryDto.setAppId(mchApp.getAppId());
        queryDto.setBusiCode(busiCode);
        queryDto.setCorpCis(mchApp.getMchNo());
        queryDto.setProjectId(mchApp.getProjectId());
        queryDto.setTrxDate(trxDate);
        queryDto.setTrxTimeStart("00:00:01");
        queryDto.setTrxTimeEnd("23:59:59");


        Result<MyPayDetailQueryResponseVo> firstPageDetailResponse = this.paymentDetailQuery(queryDto);

        if (firstPageDetailResponse.getCode() == HttpStatus.HTTP_OK && firstPageDetailResponse.getData().getTradeList() != null) {
            String curPage;
            String totalNum = firstPageDetailResponse.getData().getTotalNum();//总数
            int totalPage = Integer.parseInt(totalNum) / Integer.parseInt(queryDto.getFetchNum());//总页数

            for (int i = 1; i < totalPage; i++) {
                //开始翻页
                curPage = String.valueOf(i);
                queryDto.setCurPage(curPage);
                Result<MyPayDetailQueryResponseVo> nextPageDetailResponse = this.paymentDetailQuery(queryDto);//下一页的流水记录
                if (nextPageDetailResponse.getCode() == HttpStatus.HTTP_OK) {
                    totalTradeList.addAll(nextPageDetailResponse.getData().getTradeList());
                }
            }
            //将第一页的流水记录添加到总流水记录中
            totalTradeList.addAll(firstPageDetailResponse.getData().getTradeList());
        }

        log.info("订单号 {}, {},流水记录 {}",busiCode,trxDate,totalTradeList.size());

        SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);//开启会话

        try {
            if (!totalTradeList.isEmpty()) {


                PayOrderFlowRecordMapper mapper = sqlSession.getMapper(PayOrderFlowRecordMapper.class);

                List<String> payOrderIdSet = totalTradeList.stream()
                        .map(PaymentDetailQueryResponseV1.PaymentDetaiQueryResponseV1Trade::getBusiCode)
                        .collect(Collectors.toList());

                Set<String> transRefGuidSet = totalTradeList.stream()
                        .map(PaymentDetailQueryResponseV1.PaymentDetaiQueryResponseV1Trade::getTransRefGuid)
                        .collect(Collectors.toSet());

                Set<String> payRefguidSet = totalTradeList.stream()
                        .map(PaymentDetailQueryResponseV1.PaymentDetaiQueryResponseV1Trade::getPayRefguid)
                        .collect(Collectors.toSet());

                List<PayOrderFlowRecord> existFlowRecordList = mapper.selectList(new LambdaQueryWrapper<PayOrderFlowRecord>()
                        .in(PayOrderFlowRecord::getPayOrderId, payOrderIdSet)
                        .in(PayOrderFlowRecord::getPayRefguid, payRefguidSet)
                        .in(PayOrderFlowRecord::getTransRefGuid, transRefGuidSet));

                Map<String, PayOrderFlowRecord> existFlowRecordMap = new HashMap<>();

                if (CollectionUtil.isNotEmpty(existFlowRecordList)) {
                    existFlowRecordMap = existFlowRecordList.stream().collect(Collectors.toMap(e ->
                                    String.format("%s%s%s",
                                            e.getPayOrderId(), e.getTransRefGuid(), e.getPayRefguid()),
                            k1 -> k1, (o1, o2) -> o1));
                }

                for (PaymentDetailQueryResponseV1.PaymentDetaiQueryResponseV1Trade trade : totalTradeList) {
                    if (existFlowRecordMap.get(String.format("%s%s%s",trade.getBusiCode(),trade.getTransRefGuid(),trade.getPayRefguid())) == null) {
                        PayOrderFlowRecord record = new PayOrderFlowRecord();
                        BeanUtil.copyProperties(trade, record);
                        record.setTrxDate(DateUtils.strToLocalDateTime(String.format("%s %s",trade.getTrxDate(),trade.getTrxTime())));
                        record.setPayOrderId(trade.getBusiCode());
                        mapper.insert(record);
                    }
                }

                sqlSession.commit();
                log.info("订单号 {}, {} 订单流水记录更新完成",busiCode,payOrderIdSet.size());
            }
        }catch (BizException e) {
            log.error("订单号 {} 流水记录更新异常 {}",busiCode,e.getMessage());
            sqlSession.rollback();
        }finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
        }


    }


    /**
     * 流水记录
     * @param payOrderId 订单 号
     */
    public List<PayOrderFlowRecord> queryPayOrderFlowRecord(String payOrderId) {
        return baseMapper.selectList(new LambdaQueryWrapper<PayOrderFlowRecord>().eq(PayOrderFlowRecord::getPayOrderId, payOrderId));
    }


    /**
     * 缴费明细查询
     */
    public Result<MyPayDetailQueryResponseVo> paymentDetailQuery(PayDetailQueryDto dto) {
        MchApp mchApp = mchAppMapper.selectOne(new LambdaQueryWrapper<MchApp>().eq(MchApp::getAppId, dto.getAppId()));

        if (mchApp == null) {
            throw new BizException(BizStatus.MERCHANT_DOES_NOT_EXIST);
        }


        PayOrder payOrder = payOrderMapper.selectOne(PayOrder.gw().eq(PayOrder::getPayOrderId, dto.getBusiCode()));

        GeneralOrderDto<MyPaymentDetailQueryRequestV1> queryDto = new GeneralOrderDto<>();

        //通用参数 设置
        queryDto.setAppId(mchApp.getAppId());
        queryDto.setSignSecret(mchApp.getAppSecret());
        queryDto.setApiGwPublicKey(mchApp.getAppPublicKey());
        queryDto.setAesKey(mchApp.getAppAesKey());
        queryDto.setIfCode("icbcpay");

        //详情查询参数设置
        MyPaymentDetailQueryRequestV1 queryRequestV1 = new MyPaymentDetailQueryRequestV1();
        BeanUtil.copyProperties(dto, queryRequestV1);
        queryRequestV1.setCorpCis(mchApp.getMchNo());
        queryRequestV1.setProjectId(mchApp.getProjectId());
        queryDto.setExaData(queryRequestV1);


        PaymentDetailQueryResponseV1 responseV1 = icbcService.EPaymentDetailQueryRequestV1Function(queryDto);

        MyPayDetailQueryResponseVo responseVo = new MyPayDetailQueryResponseVo();
        BeanUtil.copyProperties(responseV1, responseVo,true);
        PayOrderVo payOrderVo = new PayOrderVo();
        BeanUtil.copyProperties(payOrder, payOrderVo);
        responseVo.setPayOrder(payOrderVo);

        if (responseV1.isSuccess()) {

            return Result.success(responseVo,BizStatus.ORDER_QUERY_SUCCESSFUL.getMsg());

        }else {

            return Result.error(BizStatus.ORDER_QUERY_FAILED.getCode(),responseVo,BizStatus.ORDER_QUERY_FAILED.getMsg());
        }

    }




}
